package com.ebt.m.proposal_v2.widget.dialog;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.graphics.Rect;
import android.net.http.SslError;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import com.ebt.m.R;
import com.ebt.m.customer.util.DisplayUtil;
import com.ebt.m.proposal_v2.base.Constant;
import com.ebt.m.proposal_v2.bean.ArgProductOption;
import com.ebt.m.proposal_v2.bean.InsuranceCalculator;
import com.ebt.m.proposal_v2.helper.WebViewCallback;
import com.ebt.m.proposal_v2.helper.WebViewSetter;
import com.ebt.m.proposal_v2.ui.ProposalNativeAPI;
import com.ebt.m.proposal_v2.utils.DataUtils;
import com.ebt.m.proposal_v2.utils.ViewUtils;
import com.ebt.m.proposal_v2.widget.view.MaxWebView;
import com.ebt.m.utils.ConfigData;
import com.ebt.m.commons.utils.Logger;
import com.ebt.m.widget.EBTProgress;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

/**
 * @author archer.qi
 *         Created on 2017/6/2.
 */
public class EBTBottomWebDialog extends EBTBottomDialogBase implements ViewTreeObserver.OnGlobalLayoutListener {
    private EBTProgress progress;
    private MaxWebView mWebView;
    private WebViewSetter mWebSetter;
    protected View netError;
    protected View serverError;
    private WebViewCallback mWebCallback;
    private ArgProductOption mArg;
    private OnProductSetListener mOnProductSetListener;

    // 产品配置结束，调用的JS方法
    public static final String JSGetProductOptions = "getCalculatorData()";

    final int SOFT_INPUT_MIN_HEIGHT = 200; // 默认软键盘最小高度为200
    private int screenHeight;
    private int softInputHeight; // 软键盘高度
    private Rect r = new Rect();
    private boolean isSoftInputOpen;

    /*该变量用于控制在软键盘弹出状态发生变化时，是否需要重置窗口大小； 如果有机型还出现软键盘遮挡输入框与底部按钮，则设为true*/
    private boolean STATRT_DIALOG_RESET_WHEN_SOFT_CHANGE = false;

    public static EBTBottomWebDialog getInstance(ArgProductOption arg) {
        EBTBottomWebDialog dialog = new EBTBottomWebDialog();
        Bundle extra = new Bundle();
        extra.putSerializable("Arg", arg);
        dialog.setArguments(extra);
        return dialog;
    }

    @Override
    public void init() {
        initArgument();
        initWebView();
        if (mArg != null) {
            setTitle(mArg.productName);
        }
        initBottomButtons();
        if (STATRT_DIALOG_RESET_WHEN_SOFT_CHANGE) {
            addKeyBoardChangedListener();
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mRooterView != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                mRooterView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        }
    }

    private void addKeyBoardChangedListener() {
        if (mRooterView == null) {
            return;
        }
        mRooterView.post(new Runnable() {
            @Override
            public void run() {
                mRooterView.getViewTreeObserver().addOnGlobalLayoutListener(EBTBottomWebDialog.this);
            }
        });
    }

    private void initArgument() {
        Bundle extra = getArguments();
        if (extra != null) {
            mArg = (ArgProductOption) extra.getSerializable("Arg");
        }
    }

    private void initBottomButtons() {
        setNegativeButton("取消", v -> {
            cancelProgress();
            dismiss();
        });
        setPositiveButton("确定", v -> {
            mWebCallback.addJsInterface(JSGetProductOptions, response -> {
                if (mOnProductSetListener != null) {
                    mOnProductSetListener.onProductSet(parseCalculator(response));
                }
            });
            cancelProgress();
            dismiss();
        });
    }

    /**
     * 解析计算器返回的保险选项
     *
     * @param json
     * @return
     */
    private InsuranceCalculator parseCalculator(String json) {
        if (TextUtils.isEmpty(json)) {
            return null;
        }
        InsuranceCalculator calculator = new InsuranceCalculator();
        try {
            JSONObject jsonObject = new JSONObject(json);
            JSONArray optionArr = jsonObject.getJSONArray("options");
            if (optionArr == null || optionArr.length() == 0) {
                return null;
            }
            for (int i = 0; i < optionArr.length(); i++) {
                JSONObject option = optionArr.getJSONObject(i);
                if (option != null) {
                    calculator.init(option.getString("fieldName"), option.getString("displayName"), option.getString("value"));
                }
            }
            return calculator;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 生成计算器访问地址
     *
     * @return
     */
    private String createWebUrl() {
        if (mArg == null) {
            return Constant.PROPOSAL_CALCULATOR_WEB_URL;
        }
        try {
            StringBuffer urlBuffer = new StringBuffer(Constant.PROPOSAL_CALCULATOR_WEB_URL);
            urlBuffer.append("proId=").append(DataUtils.encodeParamValue(mArg.productId + "")).append("&");
            urlBuffer.append("age=").append(DataUtils.encodeParamValue(mArg.age)).append("&");
            urlBuffer.append("sex=").append(DataUtils.encodeParamValue(mArg.sex)).append("&");
            urlBuffer.append("profession=").append(DataUtils.encodeParamValue(mArg.profession)).append("&");
            urlBuffer.append("birthday=").append(DataUtils.encodeParamValue(mArg.birthday)).append("&");
            if (mArg.isExemptRisk) {
                urlBuffer.append("isExempt=true").append("&");
            }
            urlBuffer.append("options=").append(DataUtils.encodeParamValue(mArg.createOptionsJson()));
            Logger.i("->编辑计划书产品Cal-Url: " + URLDecoder.decode(urlBuffer.toString(), "UTF-8"));
            Logger.i("->>>>Cal-Url: " + urlBuffer.toString());
            return urlBuffer.toString();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return Constant.PROPOSAL_CALCULATOR_WEB_URL;
    }

    @SuppressLint("WrongViewCast")
    private void initWebView() {
        View mainView = LayoutInflater.from(getContext()).inflate(R.layout.webview_bottom_calculator, null);
        progress = (EBTProgress) mainView.findViewById(R.id.loading_progress);
        showProgress();
        mWebView = mainView.findViewById(R.id.web_view);
        this.netError = mainView.findViewById(R.id.no_net_container);
        this.serverError = mainView.findViewById(R.id.net_slow_container);
        this.netError.findViewById(R.id.load_refresh_net).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                hideFailView();
                mWebView.reload();
            }
        });
        this.serverError.findViewById(R.id.load_refresh).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                hideFailView();
                mWebView.reload();
            }
        });
        mWebSetter = new WebViewSetter()
                .with(mWebView)
                .supportJavaScript()
                .wrapViewPort()
//                .noCache()
                .encodingTextByUTF8()
                .showNetworkImage()
                .allowFileAccess()
                .javaScriptCanOpenWindow()
                .loadImagesAuto()
                .enableDomStorage()
                .loadUrl(createWebUrl());
        mWebView.setWebViewClient(new WebViewClient() {
            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                String url = request.getUrl().toString();
                if (url != null && (url.startsWith("http") || url.startsWith("https"))) {
                    view.loadUrl(ViewUtils.processUrl(url));
                    return true;
                }
                return super.shouldOverrideUrlLoading(view, request);
            }

            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                if (error.getPrimaryError() == SslError.SSL_INVALID) {
                    handler.proceed();
                } else {
                    handler.cancel();
                }
            }

            @Override
            // 新版本，只会在Android6及以上调用
            @TargetApi(Build.VERSION_CODES.M)
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError
                    error) {
                super.onReceivedError(view, request, error);
                view.stopLoading();
                view.clearView();
                // 或者：if(request.getUrl().toString() .equals(getUrl()))
                if (request.isForMainFrame()) {
                    // 在这里显示自定义错误页
                    showFail(error.getErrorCode());
                }
            }

            /**
             * 旧API在新API中也会被调用
             *
             * @param view
             * @param errorCode
             * @param description
             * @param failingUrl
             */
            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                super.onReceivedError(view, errorCode, description, failingUrl);
                view.stopLoading();
                view.clearView();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    return;
                }
                showFail(errorCode);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                cancelProgress();
            }
        });
        mWebCallback = new WebViewCallback()
                .with(mWebView)
                .addNativeInterface(new ProposalNativeAPI(getContext()), Constant.JSCallInstance);
        addDialogBody(mainView);
    }

    /**
     * 隐藏错误view
     */
    private void hideFailView() {
        netError.setVisibility(View.GONE);
        serverError.setVisibility(View.GONE);
    }

    protected void showFail(int errorCode) {
        Logger.e("errorCode = " + errorCode);
        if (mWebView.canGoBack()) {
            return;
        }
        int type = 0;//网络不可用
        switch (errorCode) {
            case WebViewClient.ERROR_HOST_LOOKUP://网络不通
                type = 1;
                break;
            case WebViewClient.ERROR_TIMEOUT:// /** Connection timed out */
                type = 2;
                break;
            case WebViewClient.ERROR_CONNECT:///** Failed to connect to the server */
                type = 1;
                break;
            case WebViewClient.ERROR_IO://    /** Failed to read or write to the server */
                type = 2;
                break;
            default://默认加载失败
//                loadFail.setErrorType(EBTErrorView.ErrorType.LOAD_ERROR);
                break;
        }
        showFailView(type);
    }

    /**
     * 显示错误view
     *
     * @param type
     */
    private void showFailView(int type) {
        if (type == 1) {
            if (isAdded()){
                Toast.makeText(getContext(), getResources().getString(R.string.network_fail), Toast.LENGTH_SHORT).show();
            }
            netError.setVisibility(View.VISIBLE);
            serverError.setVisibility(View.GONE);
        } else if (type == 2) {
            netError.setVisibility(View.GONE);
            serverError.setVisibility(View.VISIBLE);
        }
    }

    /**
     * 添加产品编辑结果返回
     *
     * @param listener
     */
    public void addProductSetListener(OnProductSetListener listener) {
        mOnProductSetListener = listener;
    }

    public interface OnProductSetListener {
        /**
         * 主附险参数编辑返回
         */
        void onProductSet(InsuranceCalculator calculator);
    }

    @Override
    public void onGlobalLayout() {
        if (mRooterView == null) {
            return;
        }
        if (screenHeight == 0) {
            screenHeight = DisplayUtil.getScreenHeight(getContext());
        }
        mRooterView.getWindowVisibleDisplayFrame(r);
        /**
         * 没有弹出软键盘，rect.bottom位于屏幕底部，rect.bottom = screenHeight
         * 弹出软键盘， rect.bottom < screenHeight
         */

        if (screenHeight - r.bottom < SOFT_INPUT_MIN_HEIGHT) {
            if (!isSoftInputOpen) {
                return;
            }
            isSoftInputOpen = false;
        } else {
            if (isSoftInputOpen) {
                return;
            }
            isSoftInputOpen = true;
            if (softInputHeight == 0) {
                softInputHeight = screenHeight - r.bottom; // 计算软键盘高度
            }
        }
    }

    private void printLog(String log) {
        if (ConfigData.DEBUG) {
            Logger.i(log);
        }
    }

    public void showProgress() {
        if (isAdded()) {
            showProgressDialog();
        }
    }

    private void showProgressDialog() {
        progress.setVisibility(View.VISIBLE);
    }

    public void cancelProgress() {
        if (isAdded()){
            progress.setVisibility(View.GONE);
        }
    }

}
